#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (c) 2025 Huawei Device Co., Ltd.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

import re
import json
import logging
from utils import utils_data, ErrorInfoBuilder

logger = logging.getLogger('my_logger')


def update_state(char, in_comment, in_string, stripped_line, i):
    if in_comment:
        if char == '*' and i < len(stripped_line) - 1 and stripped_line[i + 1] == '/':
            in_comment = False
            i += 1
    elif in_string:
        if char == in_string and (i == 0 or stripped_line[i - 1] != '\\'):
            in_string = False
    elif char == '/' and i < len(stripped_line) - 1:
        if stripped_line[i + 1] == '/':
            return True, in_comment, in_string, i
        elif stripped_line[i + 1] == '*':
            in_comment = True
            i += 1
        elif char == '"' or char == "'":
            in_string = char
    return False, in_comment, in_string, i


def get_function_content(file_path, pattern):
    function_content = []
    function_line = ""
    inside_function = False
    open_braces_count = 0
    in_comment = False
    in_string = False
    it_start_line = None
    with open(file_path, 'r', encoding='utf-8') as file:
        for line_num, line in enumerate(file, start=1):
            stripped_line = line.strip()
            if not inside_function:
                if re.search(pattern, line):
                    inside_function = True
                    open_braces_count = stripped_line.count('{')
                    function_line += line
                    it_start_line = line_num 
            else:
                function_line += line
                i = 0
                break_loop = False
                while i < len(stripped_line) and not break_loop:
                    char = stripped_line[i]
                    break_loop, in_comment, in_string, i = update_state(char, in_comment, in_string, stripped_line, i)
                    if char == '{':
                        open_braces_count += 1
                    elif char == '}':
                        open_braces_count -= 1
                        if open_braces_count == 0:
                            break
                    i += 1
                if open_braces_count == 0:
                    function_content.append((it_start_line, function_line)) 
                    function_line = ""
                    inside_function = False
    return function_content


def check_assertion():
    assertion_pattern = re.compile(
        r'(assertClose|assertContain|assertEqual|assertFail|assertFalse|assertTrue|assertInstanceOf|assertLarger'
        r'|assertLess|assertNull|assertThrowError|assertUndefined|assertNaN|assertNegUnlimited|assertPosUnlimited'
        r'|assertDeepEquals|assertPromiseIsPending|assertPromiseIsRejected|assertPromiseIsRejectedWith'
        r'|assertPromiseIsRejectedWithError|assertPromiseIsResolved|assertPromiseIsResolvedWith|expectFail|expectTure|expectFalse|expectEqual|expectSuccess)')

    file_entities = utils_data.get_file()
    if not file_entities:
        logger.error("未获取到文件信息")
        return

    has_error = False

    for file_entity in file_entities:
        if file_entity.file_name.endswith('.test.js') or file_entity.file_name.endswith('.test.ets'):
            file_path = file_entity.full_path
            language = "arkts" if file_entity.file_name.endswith('.test.ets') else "javascript"

            function_content = get_function_content(file_path, r"it\((\"|').+?\1,.+,.+{")
            for line_num, content in function_content:
                assertions = assertion_pattern.findall(content)
                if not assertions:
                    match = re.search(r"it\((\"|').+?\1,.+,.+{", content)
                    if match:
                        it_line_code = match.group(0)
                        error_info = ErrorInfoBuilder() \
                            .set_buggy_file_path(file_entity.file_path) \
                            .set_defect_type("XTS.CHECK.ASSERTION.01") \
                            .set_description("测试用例没有包含断言") \
                            .set_main_buggy_line(line_num) \
                            .set_main_buggy_code(it_line_code) \
                            .set_language(language) \
                            .build()

                        utils_data.write_error_to_json_file(error_info)
                        logger.info(json.dumps(error_info, indent=4, ensure_ascii=False))
                        has_error = True

    if has_error:
        logger.info("测试用例断言检查完成，错误信息已写入xts_result.json")
    else:
        logger.info("测试用例断言检查通过")